import { Button, Form, Input, message, Drawer, Modal, Cascader, Select,Table, Space, Checkbox, Collapse, Spin, Radio } from "antd"
import { useImperativeHandle, useState, useRef, useEffect } from 'react';
import Upload, {handleValue}  from '../../components/upload'
import Maps  from '../../components/maps'
import * as apis from '../../lib/api'
import http from '../../lib/http'
import FabricParam from '../../components/fabric_param'
import Client3D from "../../lib/three";
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader'
import { useLocation, useNavigate } from "react-router-dom";
import { cloneDeep } from 'lodash';
import md5 from "md5";

const { Panel } = Collapse;

const Index = (props) => {
    const [isModalOpen, setIsModalOpen] = useState(false)
    const [form] = Form.useForm()
    const paramMaps = Form.useWatch("maps",form)
    const paramPath = Form.useWatch("path",form)
    const [loading, setLoading] = useState(false)
    const [fieldsValue, asetFieldsValue] = useState({})
    const l = useLocation()
    const n = useNavigate()
    const [threeClient, setThreeClient] = useState(null)
    const [meshs, setMeshs] = useState([])
    const [curMeshIndex, setCurMeshIndex] = useState()
    const [lookupMesh, setLookupMesh] = useState(false)
    const [baseOpen, setBaseOpen] = useState(false)
    const [disabledObj, setDisabledObj] = useState(false)
    const canvasRef = useRef()

    useImperativeHandle(props.funcs, () => ({
        setIsModalOpen,
        resetFields: form.resetFields,
        setFieldsValue: async (data) => {
            if(data.items){
                data.items = JSON.parse(data.items)
                data.maps = data.items[0].maps
            }
            asetFieldsValue(data)
            
            form.setFieldsValue(data)
            if(Object.keys(data).length === 0){
                setMeshs([])
                return
            }

            setDisabledObj(true)

            //启动3D场景
            let ops = {
                canvasDom: canvasRef?.current,
                canvasWidth: 375,
                canvasHeight: 667
            }
            //初始化3DClient
            let client = new Client3D(ops)
            setThreeClient(client)
            //启动3D场景
            client.start()

            let path = data.path[0].url
            setLoading(true)

            client.loadModel(process.env.REACT_APP_OSS_URL+path, (p) => {
                console.log(p)
            }).then(r => {
                const newMesh = []
                const meshs = new Map()
                for(let i=0;i<r?.getObjects()?.children?.length;i++){
                    let item = r?.getObjects()?.children[i]
                    if (item.isMesh) {
                        let f = data.items?.find(j => j.code === item.name)
                        if(f){
                            newMesh.push(f)
                        }else{
                            newMesh.push({
                                code: item.name,
                                txt: item.name,
                                img: "",
                                camera: null,
                                items: []
                            })
                        }
                        meshs.set(item.name, 1)
                    }
                }

                if(meshs.size !== newMesh.length){
                    message.error(`模型内有重复版片名称，请重新上传`)
                    client?.destroy()
                    return
                }
                setMeshs(newMesh)
                setTimeout(async () => {
                    collapseChange(newMesh[0].code, client, newMesh)
                    if(data.items){
                        await loadMap(data.items, client)
                    }
                    setLoading(false)
                },300)
            })
        }
    }));

    useEffect(()=>{
        if(!isModalOpen){
            threeClient?.destroy()
        }
    },[isModalOpen])

    const headTxt = (v) => {
        let sy = {
            width: 300,
            display: "inline-block",
            textOverflow: "ellipsis",
            overflow: "hidden",
            whiteSpace: "nowrap"
        }
        return <div>
            {
                meshs[curMeshIndex]?.code === v.code ? <span style={{...sy,color: "red"}}>  
                [当前选中]{v.txt}</span>:<span style={sy}>{v.txt}</span>
            }
            {/* <span style={{width: 20,height: 20,display: "inline-block"}}></span> */}
        </div>
    }

    const columns = [
        {
          title: '名称',
          dataIndex: 'name',
          key: 'name',
          render: (v,r,dx) => (
            <Input placeholder="请输入" allowClear value={v} onChange={e => {
                let cpMeshs = cloneDeep(meshs)
                cpMeshs[curMeshIndex].items[dx].name = e.target.value
                setMeshs(cpMeshs)
            }} />
          )
        },
        {
            title: '封面',
            dataIndex: 'cover',
            key: 'cover',
            render: (v,r,dx) => {
                let cpMeshs = cloneDeep(meshs)
                return <Upload value={handleValue(v)} onChange={e => {
                    if(e && e.length !== 0){
                        cpMeshs[curMeshIndex].items[dx].cover = e[0].url
                    }else{
                        cpMeshs[curMeshIndex].items[dx].cover = ""
                    }

                    setMeshs(cpMeshs)
                }} />
            }
        },
        {
          title: '部件',
          dataIndex: 'path',
          key: 'path',
          render: (v,r,dx) => (
            <Upload accept=".obj" value={handleValue(v)} onChange={e => {
                let cpMeshs = cloneDeep(meshs)
                if(e && e.length !== 0){
                    cpMeshs[curMeshIndex].items[dx].path = e[0].url
                }else{
                    cpMeshs[curMeshIndex].items[dx].path = ""
                }
                setMeshs(cpMeshs)
            }} />
          )    
        },
        {
            title: '设计文件',
            dataIndex: 'design_file_path',
            key: 'design_file_path',
            render: (v,r,dx) => (
              <Upload size={1024*200} value={handleValue(v)} accept="*" onChange={e => {
                  let cpMeshs = cloneDeep(meshs)
                  if(e && e.length !== 0){
                    cpMeshs[curMeshIndex].items[dx].design_file_path = e[0].url
                  }else{
                    cpMeshs[curMeshIndex].items[dx].design_file_path = ""
                  }
                  setMeshs(cpMeshs)
              }} />
            )    
        },
        {
            title: '操作',
            dataIndex: 'a',
            key: 'a',
            render: (v,r,dx) => (
                <>
                    <Space>
                        <Button loading={loading} style={{padding: 0}} type="link" onClick={async ()=> {
                            console.log(r)
                            setLoading(true)
                            try {
                                threeClient.replaceGeometry(meshs[curMeshIndex].code, r.path)
                            } catch (error) {
                                message.error("加载部件失败")
                            }
                            setLoading(false)
                        }}>预览</Button>
                        <Button loading={loading} style={{padding: 0}} type="link" danger onClick={()=> {
                            Modal.confirm({
                                title: "提示",
                                content: <p>确定删除吗?</p>,
                                onOk: async () => {
                                    let cpMeshs = cloneDeep(meshs)
                                    cpMeshs[curMeshIndex].items.splice(dx,1)
                                    setMeshs(cpMeshs)
                                }
                            })
                        }}>删除</Button>
                    </Space>
                </>
            )
        }
    ];

    const loadAndCheck = (path) => {
        const meshs = new Map()
        const marr = []
        let loader = new OBJLoader()
        let modelType = ""
        if(path.indexOf(".obj") !== -1){
            modelType = "obj"
        }else{
            modelType = "glb"
            loader = new GLTFLoader()
        }
        return new Promise((resolve, reject) => {
            loader.load(path, async (objects) => {
                if (modelType === "glb"){
                    objects = objects.scene
                }
                for (let i = 0; i < objects.children.length; i++) {
                    let child = objects.children[i]
                    if (child.isMesh) {
                        meshs.set(child.name,1)
                        marr.push(child.name)
                    }
                }
                // console.log(marr,meshs)
                if(meshs.size !== marr.length){
                    reject(`模型内有重复版片名称，请重新上传`)
                    return
                }
                resolve(null)
            }, xhr => {
                // let p = (xhr.loaded / xhr.total) * 100;
                // onProgress(p.toFixed(2))
            }, error => {
                reject(error)
            })
        })
    }

    //加载贴图
    const loadMap = async (items, cli = threeClient) => {
        for(let i=0;i < items.length;i++){
            let item = items[i]
            let code = item.code
            //清除之前的贴图
            cli.clearMap(code)
            //加载贴图
            for(let m=0;m<item?.maps?.length;m++){
                let a = item.maps[m]
                if(!a.url){
                    continue
                }              
                await cli.setMap(a.url, a.map, code)
            }
        }
    }

    //是否有模型
    const isHaveModel = () => {
        return paramPath && paramPath.length !== 0
    }

    const modelChange = (val) => {
        console.log(val)
        if(val && val.length !== 0){
            setDisabledObj(false)
            //启动3D场景
            let ops = {
                canvasDom: canvasRef?.current,
                canvasWidth: 375,
                canvasHeight: 667
            }
            //初始化3DClient
            let client = new Client3D(ops)
            setThreeClient(client)
            //启动3D场景
            client.start()

            let path = val[0].url
            setLoading(true)

            client.loadModel(process.env.REACT_APP_OSS_URL+path, (p) => {
                console.log(p)
            }).then(r => {
                const newMesh = []
                const meshs = new Map()
                for(let i=0;i<r?.getObjects()?.children?.length;i++){
                    let item = r?.getObjects()?.children[i]
                    if (item.isMesh) {
                        meshs.set(item.name,1)
                        newMesh.push({
                            code: item.name,
                            txt: item.name,
                            img: "",
                            camera: null,
                            items: []
                        })
                    }
                }
                if(meshs.size !== newMesh.length){
                    message.error(`模型内有重复版片名称，请重新上传`)
                    client?.destroy()
                    return
                }

                setMeshs(newMesh)
                setTimeout(() => {
                    collapseChange(newMesh[0].code, client, newMesh)
                },300)
                setLoading(false)
            })
        }else{
            threeClient?.destroy()
        }
    }

    // useEffect(() => {
    //     if(paramMaps?.length !== 0){
    //         setLoading(true)
    //         loadMap(paramMaps).then(r => {
    //             setLoading(false)
    //         })
    //     }
    // },[JSON.stringify(paramMaps)])

    // useEffect(() => {
    //     if(paramPath && paramPath.length !== 0){
            
    //     }else{
    //         threeClient?.destroy()
    //     }
    // },[paramPath])

    

    const submit = async () => {
        try {
            const data = await form.validateFields()
            console.log(data)
            const post = {
                cover: data.cover[0].url,
                path: data.path[0].url,
                name: data.name, 
                design_file_path: data.design_file_path[0].url,
                tags: data?.tags?.join(),
                category_id: data.category_id[0] ? data.category_id[0]:0, 
                second_category_id: data.category_id[1] ? data.category_id[1]:0, 
                three_category_id: data.category_id[2] ? data.category_id[2]:0,
                items: JSON.stringify(meshs)
            }
            setLoading(true)

            if(!fieldsValue.id){
                try {
                    await http.post(apis.MODEL_CREATE, post)
                    setIsModalOpen(false)
                    message.success("新建成功")
                    props.onRefresh && props.onRefresh(1)
                } catch (error) {
                    
                }
                setLoading(false)
            }else{
                try {
                    post.id = fieldsValue.id
                    await http.post(apis.MODEL_UPDATE, post)
                    setIsModalOpen(false)
                    message.success("更新成功")
                    props.onRefresh && props.onRefresh()
                } catch (error) {
                    
                }
                setLoading(false)
            }
        } catch (error) {
            console.log(error)
            setLoading(false)
        }
    }

    const collapseChange = (k, c = threeClient, ms = meshs) => {
        let fi = ms?.findIndex(i => i.code === k)
        setCurMeshIndex(fi)
        c.activate(k)
    } 


    return (
        <>
            <Drawer 
                forceRender
                open={isModalOpen} 
                onClose={() => {
                    if(loading) return 
                    setIsModalOpen(false)
                }}
                bodyStyle={{padding: 0}}
                width="100vw"
                title={!fieldsValue.id ? '新增模型':'更新模型'}
                footer={null
                    // <div style={{textAlign: "right"}}>
                    //     <Space>
                    //         <Button loading={loading} onClick={() => setIsModalOpen(false)}>取消</Button>
                    //         <Button loading={loading} type="primary" onClick={submit}>确定</Button>
                    //     </Space>
                    // </div>
                }
                extra={
                    <Space>
                        <Button loading={loading} type="primary" onClick={submit}>保存</Button>
                    </Space>
                }
            >
                <Spin spinning={loading}>
                    <div style={{display: "flex"}}>
                        <div style={{padding: 8,width: 400,height: 667,flexShrink: 0,overflowY: "auto", overflowX: "hidden"}}>
                            <div style={{paddingLeft: 20}}>
                                <h4>基础信息 <Button onClick={() => setBaseOpen(!baseOpen)} type="link">{baseOpen ? "展开":"收起"}</Button></h4>
                                <Form hidden={baseOpen} form={form} autoComplete="off">
                                    <Form.Item hidden={!isHaveModel()} name="name" label="名称">
                                        <Input placeholder="请输入" />
                                    </Form.Item>
                                    <Form.Item hidden={!isHaveModel()} name="tags" label="标签">
                                        <Select
                                            mode="tags"
                                            placeholder="输入标签"
                                        />
                                    </Form.Item>
                                    <Form.Item hidden={!isHaveModel()} name="category_id" label="分类" rules={[{required: true, message: "请选择"}]}>
                                        <Cascader style={{width: "100%"}} allowClear options={props?.category} placeholder="请选择" />
                                    </Form.Item>
                                    <Form.Item hidden={!isHaveModel()} name="cover" label="封面" rules={[{required: true, message: "请上传"}]}>
                                        <Upload />
                                    </Form.Item>
                                    <Form.Item name="path" label="模型" rules={[{required: true, message: "请上传"}]}>
                                        <Upload size={1024*50} disabled={disabledObj} accept=".obj,.glb" onChange={modelChange} />
                                    </Form.Item>
                                    <div style={{fontSize: 12, color: "red", marginTop: -20, marginBottom: 12}}>* 模型上传保存后不可更改</div>
                                    <Form.Item hidden={!isHaveModel()} name="design_file_path" label="源文件" rules={[{required: true, message: "请上传"}]}>
                                        <Upload size={1024*200} accept="*" />
                                    </Form.Item>
                                    <Form.Item hidden={!isHaveModel()} name="maps" label="贴图">
                                        <Maps onChange={async val => {
                                            console.log(val)
                                            setLoading(true)
                                            let cpMeshs = cloneDeep(meshs)
                                            for(let i=0;i<cpMeshs.length;i++){
                                                cpMeshs[i].maps = val
                                            }
                                            setMeshs(cpMeshs)
                                            await loadMap(cpMeshs)
                                            setLoading(false)
                                        }} />
                                    </Form.Item>
                                </Form>
                                <h4 style={{display: isHaveModel() ? "block":"none"}}>部位列表({meshs?.length})</h4>
                                <div style={{display: isHaveModel() ? "block":"none"}}>
                                    <Space>
                                        <Checkbox checked={lookupMesh} onChange={(e) => {
                                            setLookupMesh(e.target.checked)
                                            const codes = []
                                            for(let i=0;i<meshs.length;i++){
                                                if(meshs[i].renderFabric){
                                                    codes.push(meshs[i].code)
                                                }
                                            }
                                            if(e.target.checked){
                                                threeClient.setMaterialColor(codes, "red")
                                            }else{
                                                threeClient.setMaterialColor(codes, "#ffffff")
                                            }
                                        }}>已激活版片</Checkbox>
                                        <Checkbox onChange={(e) => {
                                            let cpMesh = cloneDeep(meshs)
                                            const codes = []
                                            for(let i=0;i<meshs.length;i++){
                                                if(e.target.checked){
                                                    cpMesh[i].renderFabric = true
                                                    if(lookupMesh){
                                                        //threeClient.setMaterialColor([meshs[i].code], "#ffffff")
                                                        threeClient.setMaterialColor([meshs[i].code], "red")
                                                    }else{
                                                        
                                                    }
                                                }else{
                                                    cpMesh[i].renderFabric = false
                                                    if(lookupMesh){
                                                        threeClient.setMaterialColor([meshs[i].code], "#ffffff")
                                                        //threeClient.setMaterialColor([meshs[i].code], "red")
                                                    }else{
                                                        
                                                    }
                                                }
                                            }
                                            setMeshs(cpMesh)
                                        }}>全选</Checkbox> 
                                    </Space>
                                </div>
                            </div>
                            <Collapse
                                accordion
                                ghost
                                style={{ paddingBottom: 100, display: isHaveModel() ? "block":"none" }}
                                activeKey={meshs[curMeshIndex]?.code}
                                onChange={(k) => {
                                    if(!k){
                                        return
                                    }
                                    collapseChange(k)
                                }}
                            >
                                {
                                    meshs?.map((v,k) => (
                                        <Panel header={headTxt(v)} key={v.code}>
                                            <Space>
                                                <Button onClick={() => {
                                                    let cpMeshs = cloneDeep(meshs)
                                                    cpMeshs[k].items.push({
                                                        id: new Date().getTime(),
                                                        name: "",
                                                        cover: "",
                                                        path: "",
                                                        design_file_path: ""
                                                    })
                                                    setMeshs(cpMeshs)
                                                }} type="link" style={{padding: 0}}>添加部件</Button>
                                                <Radio name='isModel' checked={!!v.isModel} onChange={(e) => {
                                                    let cpMeshs = cloneDeep(meshs)
                                                    for(let i=0;i<cpMeshs.length;i++){
                                                        cpMeshs[i].isModel = false
                                                    }
                                                    cpMeshs[k].isModel = e.target.checked
                                                    setMeshs(cpMeshs)
                                                }} type="link" style={{padding: 0}}>人体模特</Radio>
                                                {/* <Button onClick={() => {
                                                    let cpMeshs = cloneDeep(meshs)
                                                    cpMeshs[k].camera = cloneDeep(threeClient.getCameraPosition())
                                                    setMeshs(cpMeshs)
                                                }} type="link" style={{padding: 0}}>快照</Button>
                                                {
                                                    v.camera && <Button loading={loading} type="link" style={{padding: 0}} onClick={()=>{
                                                        threeClient.setCamera(v.camera.x,v.camera.y,v.camera.z)
                                                    }}>复位</Button>
                                                } */}
                                                <Checkbox checked={!!v.renderFabric} onChange={(e)=>{
                                                    let cpMeshs = cloneDeep(meshs)
                                                        cpMeshs[k].renderFabric = e.target.checked
                                                        setMeshs(cpMeshs)
                                                        const codes = []
                                                        for(let i=0;i<cpMeshs.length;i++){
                                                            if(lookupMesh){
                                                                threeClient.setMaterialColor([cpMeshs[i].code], "#ffffff")
                                                            }
                                                            if(cpMeshs[i].renderFabric){
                                                                codes.push(cpMeshs[i].code)
                                                            }
                                                        }
                                                        if(lookupMesh){
                                                            threeClient.setMaterialColor(codes, "red")
                                                        }
                                                        
                                                }}>激活版片</Checkbox>
                                            </Space>
                                            {/* <div style={{height: 12}}></div>
                                            <div>
                                                <Input placeholder="部位名" value={v.txt} onChange={(e)=>{
                                                    let cpMeshs = cloneDeep(meshs)
                                                    cpMeshs[k].txt = e.target.value
                                                    setMeshs(cpMeshs)
                                                }} />
                                            </div>
                                            <div style={{height: 12}}></div>
                                            <div>裁片图：</div>
                                            <div style={{height: 12}}></div>
                                            <div>
                                                <Upload value={handleValue(v.img)} onChange={e => {
                                                    let cpMeshs = cloneDeep(meshs)
                                                    if(e && e.length !== 0){
                                                        cpMeshs[k].img = e[0].url
                                                    }else{
                                                        cpMeshs[k].img = ""
                                                    }
                                                    setMeshs(cpMeshs)
                                                }} />
                                            </div> */}
                                        </Panel>
                                    ))
                                }
                            </Collapse>
                        </div>
                        <div style={{width: 12}}></div>
                        <div style={{
                            width: 375,
                            height: 667, 
                            background: "linear-gradient(180deg, rgba(238,238,238,0) 0%, #F8F8F8 100%)",
                            border: "solid 1px #f5f5f5",
                            borderTop: "none",
                            cursor: "pointer",
                            position: "relative",
                            flexShrink: 0
                        }}>
                            <canvas onPointerUp={() => {
                                if(threeClient.outlinePass.selectedObjects.length !== 0){
                                    // setBaseOpen(true)
                                    collapseChange(threeClient.outlinePass.selectedObjects[0].name)
                                }
                            }} style={{display: "block",touchAction: "none"}} ref={canvasRef}></canvas>
                        </div>
                        <div style={{width: 12}}></div>
                        <div style={{padding: 8, minWidth: 600,overflow:"auto"}}>
                            <h4>可替换部件({meshs[curMeshIndex]?.items?.length || 0})</h4>
                            <Table 
                                scroll={{y: 667 - 55}} 
                                pagination={false} 
                                rowKey={"id"} 
                                dataSource={meshs[curMeshIndex]?.items} 
                                columns={columns}
                            />
                        </div>
                    </div>
                </Spin>
            </Drawer>
        </>
    )
}

export default Index